{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# Autoencoder Nasa Randomized dataset"
   ],
   "metadata": {
    "id": "jw9FMur02UtZ"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import scipy.io\n",
    "import math\n",
    "import os\n",
    "import ntpath\n",
    "import sys\n",
    "import logging\n",
    "import time\n",
    "import sys\n",
    "import random\n",
    "\n",
    "from importlib import reload\n",
    "import plotly.graph_objects as go\n",
    "\n",
    "import tensorflow as tf\n",
    "from tensorflow import keras\n",
    "from tensorflow.keras import layers, regularizers\n",
    "from tensorflow.keras.models import Model\n",
    "\n",
    "\n",
    "IS_COLAB = False\n",
    "IS_TRAINING = True\n",
    "RESULT_NAME = \"\"\n",
    "\n",
    "if IS_COLAB:\n",
    "    from google.colab import drive\n",
    "    drive.mount('/content/drive')\n",
    "    data_path = \"/content/drive/My Drive/CEM-Data-Experiment/cem-data-experiment/\"\n",
    "else:\n",
    "    data_path = \"../../\"\n",
    "\n",
    "sys.path.append(data_path)\n",
    "from data_processing.nasa_random_data import NasaRandomizedData\n",
    "from data_processing.prepare_rul_data import RulHandler"
   ],
   "outputs": [],
   "metadata": {
    "id": "XKxZ90kO2Uta"
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Config logging"
   ],
   "metadata": {
    "id": "MfVCRISs2Utc"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "reload(logging)\n",
    "logging.basicConfig(format='%(asctime)s [%(levelname)s]: %(message)s', level=logging.DEBUG, datefmt='%Y/%m/%d %H:%M:%S')"
   ],
   "outputs": [],
   "metadata": {
    "id": "K2IvySBk2Utd"
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Load Data"
   ],
   "metadata": {
    "id": "KsbkwTX22Utf"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "train_names_20k = [\n",
    "        'Battery_Uniform_Distribution_Variable_Charge_Room_Temp_DataSet_2Post/data/Matlab/RW1',\n",
    "        'Battery_Uniform_Distribution_Variable_Charge_Room_Temp_DataSet_2Post/data/Matlab/RW2',\n",
    "        'Battery_Uniform_Distribution_Variable_Charge_Room_Temp_DataSet_2Post/data/Matlab/RW7',\n",
    "\n",
    "        #'Battery_Uniform_Distribution_Discharge_Room_Temp_DataSet_2Post/data/Matlab/RW3',\n",
    "        'Battery_Uniform_Distribution_Discharge_Room_Temp_DataSet_2Post/data/Matlab/RW4',\n",
    "        'Battery_Uniform_Distribution_Discharge_Room_Temp_DataSet_2Post/data/Matlab/RW5',\n",
    "\n",
    "        #'Battery_Uniform_Distribution_Charge_Discharge_DataSet_2Post/data/Matlab/RW9',\n",
    "        #'Battery_Uniform_Distribution_Charge_Discharge_DataSet_2Post/data/Matlab/RW10',\n",
    "        #'Battery_Uniform_Distribution_Charge_Discharge_DataSet_2Post/data/Matlab/RW11',\n",
    "]\n",
    "\n",
    "test_names_20k = [\n",
    "        'Battery_Uniform_Distribution_Variable_Charge_Room_Temp_DataSet_2Post/data/Matlab/RW8',\n",
    "        'Battery_Uniform_Distribution_Discharge_Room_Temp_DataSet_2Post/data/Matlab/RW6',\n",
    "        #'Battery_Uniform_Distribution_Charge_Discharge_DataSet_2Post/data/Matlab/RW12',\n",
    "]\n",
    "\n",
    "train_names_10k = [\n",
    "        'RW_Skewed_Low_Room_Temp_DataSet_2Post/data/Matlab/RW13',\n",
    "        'RW_Skewed_Low_Room_Temp_DataSet_2Post/data/Matlab/RW14',\n",
    "        'RW_Skewed_Low_Room_Temp_DataSet_2Post/data/Matlab/RW15',\n",
    "\n",
    "        'RW_Skewed_Low_40C_DataSet_2Post/data/Matlab/RW21',\n",
    "        'RW_Skewed_Low_40C_DataSet_2Post/data/Matlab/RW22',\n",
    "        'RW_Skewed_Low_40C_DataSet_2Post/data/Matlab/RW23',\n",
    "\n",
    "        'RW_Skewed_High_40C_DataSet_2Post/data/Matlab/RW25',\n",
    "        'RW_Skewed_High_40C_DataSet_2Post/data/Matlab/RW26',\n",
    "        'RW_Skewed_High_40C_DataSet_2Post/data/Matlab/RW27',\n",
    "]\n",
    "\n",
    "test_names_10k = [\n",
    "        'RW_Skewed_Low_Room_Temp_DataSet_2Post/data/Matlab/RW16',\n",
    "        'RW_Skewed_Low_40C_DataSet_2Post/data/Matlab/RW24',\n",
    "        'RW_Skewed_High_40C_DataSet_2Post/data/Matlab/RW28',\n",
    "]\n",
    "\n",
    "train_names_100k = [\n",
    "        'RW_Skewed_High_Room_Temp_DataSet_2Post/data/Matlab/RW17',\n",
    "        'RW_Skewed_High_Room_Temp_DataSet_2Post/data/Matlab/RW18',\n",
    "        'RW_Skewed_High_Room_Temp_DataSet_2Post/data/Matlab/RW19',\n",
    "]\n",
    "\n",
    "test_names_no_100k = [\n",
    "        'RW_Skewed_High_Room_Temp_DataSet_2Post/data/Matlab/RW20',\n",
    "]"
   ],
   "outputs": [],
   "metadata": {
    "id": "NSFp-2Rl2Utj"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "nasa_data_handler = NasaRandomizedData(data_path)\n",
    "rul_handler = RulHandler()"
   ],
   "outputs": [],
   "metadata": {
    "id": "k-yTrXQ12Utm"
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Data preparation"
   ],
   "metadata": {
    "id": "bAAxueIqkZM9"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "(train_x_10k, _, test_x_10k, _, battery_range_cycle_train_10k, battery_range_cycle_test_10k, _, _, _, _) = nasa_data_handler.get_discharge_whole_cycle_future(train_names_10k, test_names_10k)\n",
    "(train_x_20k, _, test_x_20k, _, _, _, _, _, _, _) = nasa_data_handler.get_discharge_whole_cycle_future(train_names_20k, test_names_20k)\n",
    "(train_x_100k, _, test_x_no_100k, _, _, _, _, _, _, _) = nasa_data_handler.get_discharge_whole_cycle_future(train_names_100k, test_names_no_100k)\n",
    "\n",
    "\n",
    "train_x_20k = train_x_20k[:, ::2, :]\n",
    "test_x_20k = test_x_20k[:, ::2, :]\n",
    "train_x_100k = train_x_100k[:, ::10, :]\n",
    "max_lenght = max(train_x_10k.shape[1], test_x_10k.shape[1], train_x_20k.shape[1], test_x_20k.shape[1], train_x_100k.shape[1], test_x_no_100k.shape[1])\n",
    "\n",
    "train_x = np.zeros((\n",
    "        train_x_10k.shape[0] + train_x_20k.shape[0] + train_x_100k.shape[0],\n",
    "        max_lenght,\n",
    "        train_x_10k.shape[2]))\n",
    "train_x[:train_x_10k.shape[0], :train_x_10k.shape[1], :] = train_x_10k\n",
    "train_x[train_x_10k.shape[0]:train_x_10k.shape[0]+train_x_20k.shape[0], :train_x_20k.shape[1], :] = train_x_20k\n",
    "train_x[train_x_10k.shape[0]+train_x_20k.shape[0]:, :train_x_100k.shape[1], :] = train_x_100k\n",
    "\n",
    "test_x = np.zeros((\n",
    "        test_x_10k.shape[0] + test_x_20k.shape[0] + test_x_no_100k.shape[0],\n",
    "        max_lenght,\n",
    "        test_x_10k.shape[2]))\n",
    "test_x[:test_x_10k.shape[0], :test_x_10k.shape[1], :] = test_x_10k\n",
    "test_x[test_x_10k.shape[0]:test_x_10k.shape[0]+test_x_20k.shape[0], :test_x_20k.shape[1], :] = test_x_20k\n",
    "test_x[test_x_10k.shape[0]+test_x_20k.shape[0]:, :test_x_no_100k.shape[1], :] = test_x_no_100k\n",
    "\n",
    "print(\"train shape {}\".format(train_x.shape))\n",
    "print(\"test shape {}\".format(test_x.shape))\n",
    "\n",
    "train_x = train_x[:,:11800,:]\n",
    "test_x = test_x[:,:11800,:]\n",
    "print(\"cut train shape {}\".format(train_x.shape))\n",
    "print(\"cut test shape {}\".format(test_x.shape))\n",
    "\n",
    "x_norm = rul_handler.Normalization()\n",
    "train_x, test_x = x_norm.normalize(train_x, test_x)"
   ],
   "outputs": [],
   "metadata": {
    "id": "TbntMzBZkZM9",
    "tags": []
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Model training"
   ],
   "metadata": {
    "id": "7iYU-n0K2Utq"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "if IS_TRAINING:\n",
    "    EXPERIMENT = \"autoencoder_nasa_randomized\"\n",
    "\n",
    "    experiment_name = time.strftime(\"%Y-%m-%d-%H-%M-%S\") + '_' + EXPERIMENT\n",
    "    print(experiment_name)\n",
    "\n",
    "# Model definition\n",
    "\n",
    "opt = tf.keras.optimizers.Adam(learning_rate=0.0002)\n",
    "LATENT_DIM = 15\n",
    "\n",
    "class Autoencoder(Model):\n",
    "    def __init__(self, latent_dim):\n",
    "        super(Autoencoder, self).__init__()\n",
    "        self.latent_dim = latent_dim\n",
    "        self.encoder = tf.keras.Sequential([\n",
    "            layers.Input(shape=(train_x.shape[1], train_x.shape[2])),\n",
    "            #layers.MaxPooling1D(5, padding='same'),\n",
    "            layers.Conv1D(filters=16, kernel_size=5, strides=2, activation='relu', padding='same'),\n",
    "            layers.Conv1D(filters=8, kernel_size=3, strides=2, activation='relu', padding='same'),\n",
    "            layers.Flatten(),\n",
    "            layers.Dense(self.latent_dim, activation='relu')\n",
    "        ])\n",
    "        self.decoder = tf.keras.Sequential([\n",
    "            layers.Input(shape=(self.latent_dim)),\n",
    "            layers.Dense(23600, activation='relu'),\n",
    "            layers.Reshape((2950, 8)),\n",
    "            layers.Conv1DTranspose(filters=8, kernel_size=3, strides=2, activation='relu', padding='same'),\n",
    "            layers.Conv1DTranspose(filters=16, kernel_size=5, strides=2, activation='relu', padding='same'),\n",
    "            layers.Conv1D(3, kernel_size=3, activation='relu', padding='same'),\n",
    "            #layers.UpSampling1D(5),\n",
    "        ])\n",
    "\n",
    "\n",
    "    def call(self, x):\n",
    "        encoded = self.encoder(x)\n",
    "        decoded = self.decoder(encoded)\n",
    "        return decoded\n",
    "\n",
    "autoencoder = Autoencoder(LATENT_DIM)\n",
    "autoencoder.compile(optimizer=opt, loss='mse', metrics=['mse', 'mae', 'mape', tf.keras.metrics.RootMeanSquaredError(name='rmse')])\n",
    "autoencoder.encoder.summary()\n",
    "autoencoder.decoder.summary()"
   ],
   "outputs": [],
   "metadata": {
    "id": "LSx96n4w2Uts"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "if IS_TRAINING:\n",
    "    history = autoencoder.fit(train_x, train_x,\n",
    "                                epochs=500, \n",
    "                                batch_size=32, \n",
    "                                verbose=1,\n",
    "                                validation_split=0.1\n",
    "                               )"
   ],
   "outputs": [],
   "metadata": {
    "id": "AIEcv6Ey2Utu"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "if IS_TRAINING:\n",
    "    autoencoder.save_weights(data_path + 'results/trained_model/%s/model' % experiment_name)\n",
    "\n",
    "    hist_df = pd.DataFrame(history.history)\n",
    "    hist_csv_file = data_path + 'results/trained_model/%s/history.csv' % experiment_name\n",
    "    with open(hist_csv_file, mode='w') as f:\n",
    "        hist_df.to_csv(f)\n",
    "    history = history.history"
   ],
   "outputs": [],
   "metadata": {
    "id": "oNHlqcvP2Utx"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "if not IS_TRAINING:\n",
    "    history = pd.read_csv(data_path + 'results/trained_model/%s/history.csv' % RESULT_NAME)\n",
    "    autoencoder.load_weights(data_path + 'results/trained_model/%s/model' % RESULT_NAME)\n",
    "    autoencoder.encoder.summary()\n",
    "    autoencoder.decoder.summary()"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "if not IS_TRAINING:\n",
    "    with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
    "        print(history)"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "markdown",
   "source": [
    "### Testing"
   ],
   "metadata": {
    "id": "LH5RANQIEQVx"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "results = autoencoder.evaluate(test_x, test_x, return_dict = True)\n",
    "print(results)\n",
    "max_rmse = 0\n",
    "for index in range(test_x.shape[0]):\n",
    "    result = autoencoder.evaluate(np.array([test_x[index, :, :]]), np.array([test_x[index, :, :]]), return_dict = True, verbose=0)\n",
    "    max_rmse = max(max_rmse, result['rmse'])\n",
    "print(\"Max rmse: {}\".format(max_rmse))"
   ],
   "outputs": [],
   "metadata": {
    "id": "ggNKW-VqENFN"
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Results Visualization"
   ],
   "metadata": {
    "id": "uiqyD8Bn2Utz"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "fig = go.Figure()\n",
    "fig.add_trace(go.Scatter(y=history['loss'],\n",
    "                    mode='lines', name='train'))\n",
    "fig.add_trace(go.Scatter(y=history['val_loss'],\n",
    "                    mode='lines', name='validation'))\n",
    "fig.update_layout(title='Loss trend',\n",
    "                  xaxis_title='epoch',\n",
    "                  yaxis_title='loss',\n",
    "                  width=1400,\n",
    "                  height=600)\n",
    "fig.show()"
   ],
   "outputs": [],
   "metadata": {
    "id": "jH9RrBRN2Utz"
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "train_predictions = autoencoder.predict(train_x)\n",
    "labels = ['Voltage', 'Current', 'Temperature']"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "for i in range(train_x.shape[2]):\n",
    "    fig = go.Figure()\n",
    "    fig.add_trace(go.Scatter(y=train_predictions[5,:,i],\n",
    "                        mode='lines', name='predicted'))\n",
    "    fig.add_trace(go.Scatter(y=train_x[5,:,i],\n",
    "                        mode='lines', name='actual'))\n",
    "    fig.update_layout(title='Results on training - battery new',\n",
    "                    xaxis_title='Step',\n",
    "                    yaxis_title=labels[i],\n",
    "                    width=1400,\n",
    "                    height=600)\n",
    "    fig.show()"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "for i in range(train_x.shape[2]):\n",
    "    fig = go.Figure()\n",
    "    fig.add_trace(go.Scatter(y=train_predictions[int(battery_range_cycle_train_10k[0]/2),:,i],\n",
    "                        mode='lines', name='predicted'))\n",
    "    fig.add_trace(go.Scatter(y=train_x[int(battery_range_cycle_train_10k[0]/2),:,i],\n",
    "                        mode='lines', name='actual'))\n",
    "    fig.update_layout(title='Results on training - middle life',\n",
    "                    xaxis_title='Step',\n",
    "                    yaxis_title=labels[i],\n",
    "                    width=1400,\n",
    "                    height=600)\n",
    "    fig.show()"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "for i in range(train_x.shape[2]):\n",
    "    fig = go.Figure()\n",
    "    fig.add_trace(go.Scatter(y=train_predictions[battery_range_cycle_train_10k[0]-5,:,i],\n",
    "                        mode='lines', name='predicted'))\n",
    "    fig.add_trace(go.Scatter(y=train_x[battery_range_cycle_train_10k[0]-5,:,i],\n",
    "                        mode='lines', name='actual'))\n",
    "    fig.update_layout(title='Results on training - end of life',\n",
    "                    xaxis_title='Step',\n",
    "                    yaxis_title=labels[i],\n",
    "                    width=1400,\n",
    "                    height=600)\n",
    "    fig.show()"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "test_predictions = autoencoder.predict(test_x)\n",
    "labels = ['Voltage', 'Current', 'Temperature']"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "for i in range(train_x.shape[2]):\n",
    "    fig = go.Figure()\n",
    "    fig.add_trace(go.Scatter(y=test_predictions[0,:,i],\n",
    "                        mode='lines', name='predicted'))\n",
    "    fig.add_trace(go.Scatter(y=test_x[0,:,i],\n",
    "                        mode='lines', name='actual'))\n",
    "    fig.update_layout(title='Results on testing - battery new',\n",
    "                    xaxis_title='Step',\n",
    "                    yaxis_title=labels[i],\n",
    "                    width=1400,\n",
    "                    height=600)\n",
    "    fig.show()"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "for i in range(train_x.shape[2]):\n",
    "    fig = go.Figure()\n",
    "    fig.add_trace(go.Scatter(y=test_predictions[int(battery_range_cycle_test_10k[0]/2),:,i],\n",
    "                        mode='lines', name='predicted'))\n",
    "    fig.add_trace(go.Scatter(y=test_x[int(battery_range_cycle_test_10k[0]/2),:,i],\n",
    "                        mode='lines', name='actual'))\n",
    "    fig.update_layout(title='Results on testing - middle life',\n",
    "                    xaxis_title='Step',\n",
    "                    yaxis_title=labels[i],\n",
    "                    width=1400,\n",
    "                    height=600)\n",
    "    fig.show()"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [
    "for i in range(train_x.shape[2]):\n",
    "    fig = go.Figure()\n",
    "    fig.add_trace(go.Scatter(y=test_predictions[battery_range_cycle_test_10k[0]-5,:,i],\n",
    "                        mode='lines', name='predicted'))\n",
    "    fig.add_trace(go.Scatter(y=test_x[battery_range_cycle_test_10k[0]-5,:,i],\n",
    "                        mode='lines', name='actual'))\n",
    "    fig.update_layout(title='Results on testing - end of life',\n",
    "                    xaxis_title='Step',\n",
    "                    yaxis_title=labels[i],\n",
    "                    width=1400,\n",
    "                    height=600)\n",
    "    fig.show()"
   ],
   "outputs": [],
   "metadata": {}
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "source": [],
   "outputs": [],
   "metadata": {}
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "collapsed_sections": [],
   "name": "lstm_soh_prediction_only_future.ipynb",
   "provenance": []
  },
  "interpreter": {
   "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  },
  "metadata": {
   "interpreter": {
    "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}